其他
这些手写代码会了吗?少年
The following article is from 前端食堂 Author 霍语佳
(给前端大全加星标,提升前端技能)
作者:前端食堂 公号 / 霍语佳(本文来自作者投稿)
「观感度:🌟🌟🌟🌟🌟」
「口味:蟹黄豆腐」
「烹饪时间:5min」
从略带银丝的头发和干净利落的步伐我察觉到,面前坐着的这个面试官有点深不可测。我像往常一样,准备花 3 分钟的时间给面试官来一套昨天晚上精心准备的自我介绍。我自信且得意的诉说着对过往项目所付出的心血,所做的优化取得了怎样的成果,为公司提高了多少的收入。。。
显然,面试官对我说的数字很感兴趣,嘴角微微上扬,经过了一番细节的探讨和技术的对线后。面试官拿出了一张纸。
手写代码。
注重基础的面试官是靠谱的,为了征服他,我一边讲解着实现原理一边写出了代码。
手写 call
call 和 apply 的区别:call 方法接收的是一个参数列表,apply 方法接收的是一个包含多个参数的数组。
1. context
存在就使用context
,否则是window
2.使用 Object(context)
将context
转换成对象,并通过context.fn
将this
指向context
3.循环参数,注意从 1
开始,第0
个是上下文,后面才是我们需要的参数4.将参数字符串 push
进args
5.字符串和数组拼接时,数组会调用 toString
方法,这样可以实现将参数一个个传入,并通过eval
执行6.拿到结果返回前,删除掉 fn
Function.prototype.call = function(context) {
context = context ? Object(context) : window;
context.fn = this;
let args = [];
for (let i = 1; i < arguments.length; i++) {
args.push('arguments['+ i +']');
}
let res = eval('context.fn('+ args +')');
delete context.fn;
return res;
}
手写 apply
1. apply
无需循环参数列表,传入的args
就是数组2.但是 args
是可选参数,如果不传入的话,直接执行
Function.prototype.apply = function(context, args) {
context = context ? Object(context) : window;
context.fn = this;
if (!args) {
return context.fn();
}
let res = eval('context.fn('+ args +')');
delete context.fn;
return res;
}
手写 bind
1. bind
的参数可以在绑定和调用的时候分两次传入2. bindArgs
是绑定时除了第一个参数以外传入的参数,args
是调用时候传入的参数,将二者拼接后一起传入3.如果使用 new
运算符构造绑定函数,则会改变this
指向,this
指向当前的实例4.通过 Fn
链接原型,这样fBound
就可以通过原型链访问父类Fn
的属性
Function.prototype.bind = function(context) {
let that = this;
let bindArgs = Array.prototype.slice.call(arguments, 1);
function Fn () {};
function fBound(params) {
let args = Array.prototype.slice.call(arguments) ;
return that.apply(this instanceof fBound ? this : context, bindArgs.concat(args));
}
Fn.prototype = this.prototype;
fBound.prototype = new Fn();
return fBound;
}
手写 new
1. Constructor
就是new
时传入的第一个参数,剩余的arguments
是其他的参数2.使用 obj.__proto__ = Constructor.prototype
继承原型上的方法3.将剩余的 arguments
传给Contructor
,绑定this
指向为obj
,并执行4.如果构造函数返回的是引用类型,直接返回该引用类型,否则返回 obj
const myNew = function() {
let Constructor = Array.prototype.shift.call(arguments);
let obj = {};
obj.__proto__ = Constructor.prototype;
let res = Constructor.apply(obj, arguments);
return res instanceof Object ? res : obj;
}
手写 instanceOf
1.在 left
的原型链中层层查找,是否有原型等于prototype
2.确定边界条件,如果 left === null
,即找到头没找到返回false
,right === left
,即找到返回true
3. left = left.__proto__
,不停的向上查找
const myInstanceof = function(left, right) {
right = right.prototype;
left = left.__proto__;
while (true) {
if (left === null) {
return false;
}
if (right === left) {
return true;
}
left = left.__proto__;
}
}
手写 Object.create
新建一个空的构造函数 F
,然后让F.prototype
指向obj
,最后返回F
的实例
const myCreate = function (obj) {
function F() {};
F.prototype = obj;
return new F();
}
觉得本文对你有帮助?请分享给更多人
关注「前端大全」加星标,提升前端技能
好文章,我在看❤️